﻿//------------------------------------------------------------------------------
// ╭─────────────────────────────╮
// │ ╭─╮     ╭─╮              TM │   ╠═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╣
// │ │ │     │ │                 │                                           ☺  
// │ │ ╰───╮ │ │ ╭─────╮ ╭─────╮ │     Name:Wedn.Net 字符串处理工具类    ♮ ♪ ♩
// │ │ ╭─╮ │ │ │ │ ╭─╮ │ │ ╭─╮ │ │                                    ♫ ♭      
// │ │ ╰─╯ │ │ │ │ ╰─╯ │ │ ╰─╯ │ │     Author:iceStone               ♬ ♪       
// │ └─────╯ └─╯ ╰─────╯ ╰───╮ │ │     Chinese:汪磊                              
// │                     ┌───╯ │ │                                              
// │                     ╰─────╯ │   ╠═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╣
// ╰─────────────────────────────╯                                              
//------------------------------------------------------------------------------
using System;
using System.Web;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.IO;
using System.Web.Security;

namespace Wedn.Net.Utility
{
    /// <summary>
    /// 字符串处理工具类
    /// </summary>
    public static class StringHelper
    {
        #region 字符串转换和操作

        /// <summary>
        /// 将指定普通文本转换成HTML文本, 返回转换后HTML文本
        /// </summary>
        /// <param name="content">要转换的普通文本</param>
        /// <returns>HTML文本</returns>
        public static string TextToHtml(string content)
        {
            var sb = new StringBuilder(content);
            sb.Replace("&", "&amp;");
            sb.Replace("<", "&lt;");
            sb.Replace(">", "&gt;");
            sb.Replace("\"", "&quot;");
            sb.Replace(" ", "&nbsp;");
            sb.Replace("\t", "&nbsp;&nbsp;");
            sb.Replace("\r", "");
            sb.Replace("\n", "<br />");
            return sb.ToString();
        }

        /// <summary>
        /// 将指定HTML文本转换成普通文本, 返回转换后普通文本
        /// </summary>
        /// <param name="content">要转换的HTML文本</param>
        /// <returns>普通文本</returns>
        public static string HtmlToText(string content)
        {
            var sb = new StringBuilder(content);
            sb.Replace("<br />", "\n");
            sb.Replace("<br/>", "\n");
            sb.Replace("&nbsp;&nbsp;", "\t");
            sb.Replace("&nbsp;", " ");
            sb.Replace("&#39;", "\'");
            sb.Replace("&quot;", "\"");
            sb.Replace("&gt;", ">");
            sb.Replace("&lt;", "<");
            sb.Replace("&amp;", "&");
            return sb.ToString();
        }

        /// <summary>
        /// 对字符串进行 HTML 编码并返回已编码的字符串
        /// </summary>
        /// <param name="content">要编码的文本字符串</param>
        /// <returns>HTML 已编码的文本</returns>
        public static string HtmlEncode(string content)
        {
            return HttpContext.Current.Server.HtmlEncode(content);
        }

        /// <summary>
        ///  对 HTML 编码的字符串进行解码，并返回已解码的字符串
        /// </summary>
        /// <param name="content">要解码的文本字符串</param>
        /// <returns>已解码的字符串</returns>
        public static string HtmlDecode(string content)
        {
            return HttpContext.Current.Server.HtmlDecode(content);
        }

        /// <summary>
        /// 对 URL 字符串进行编码, 返回 URL 字符串的编码结果
        /// </summary>
        /// <param name="str">要编码的文本</param>
        /// <returns>一个已编码的字符串</returns>
        public static string UrlEncode(string str)
        {
            return HttpUtility.UrlEncode(str);
        }

        /// <summary>
        /// 对 URL 字符串进行解码, 返回 URL 字符串的解码结果
        /// </summary>
        /// <param name="str">要解码的文本</param>
        /// <returns>解码结果</returns>
        public static string UrlDecode(string str)
        {
            return HttpUtility.UrlDecode(str);
        }

        /// <summary>
        /// 移除Html标记
        /// </summary>
        /// <param name="htmlstring">包括HTML的源码</param>   
        ///<returns>已经去除后的文字</returns>   
        public static string RemoveHtml(string htmlstring)
        {
            //删除脚本和嵌入式CSS   
            htmlstring = Regex.Replace(htmlstring, @"<script[^>]*?>.*?</script>", "", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"<style[^>]*?>.*?</style>", "", RegexOptions.IgnoreCase);

            //删除HTML   
            var regex = new Regex("<.+?>", RegexOptions.IgnoreCase);
            htmlstring = regex.Replace(htmlstring, "");
            htmlstring = Regex.Replace(htmlstring, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"-->", "", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"<!--.*", "", RegexOptions.IgnoreCase);

            htmlstring = Regex.Replace(htmlstring, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"&(nbsp|#160);", "   ", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);
            htmlstring = Regex.Replace(htmlstring, @"&#(\d+);", "", RegexOptions.IgnoreCase);

            return htmlstring.Replace("<", "").Replace(">", "").Replace("\r\n", "");
        }

        /// <summary>
        /// 编码成 sql 文本可以接受的格式
        /// </summary>
        public static string SqlEncode(string sql)
        {
            if (string.IsNullOrEmpty(sql))
            {
                return string.Empty;
            }
            return sql.Trim().Replace("'", "''");
        }

        /// <summary>
        /// string型转换为int型,转换失败返回缺省值
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <param name="def">缺省值</param>
        /// <returns>转换后的int类型结果</returns>
        public static int StrToInt(string str, int def)
        {
            return IsInt(str) ? int.Parse(str) : def;
        }

        /// <summary>
        /// string型转换为int型,转换失败返回0
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <returns>转换后的int类型结果</returns>
        public static int StrToInt(string str)
        {
            return IsInt(str) ? int.Parse(str) : 0;
        }

        /// <summary>
        /// string型转换为bool型,转换失败返回缺省值
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <param name="def">缺省值</param>
        /// <returns>转换后的bool类型结果</returns>
        public static bool StrToBoolean(string str, bool def)
        {
            bool b;
            return bool.TryParse(str, out b) ? b : def;
        }

        /// <summary>
        /// string型转换为bool型,转换失败返回false
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <returns>转换后的bool类型结果</returns>
        public static bool StrToBoolean(string str)
        {
            bool b;
            return bool.TryParse(str, out b) ? b : false;
        }

        /// <summary>
        /// string型转换为DateTime型,转换失败返回最小时间
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <returns>转换后的DateTime类型结果</returns>
        public static DateTime StrToDataTime(string str)
        {
            DateTime dt;
            return DateTime.TryParse(str, out dt) ? dt : DateTime.MinValue;
        }

        /// <summary>
        /// string型转换为DateTime型,转换失败返回缺省值
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <returns>转换后的DateTime类型结果</returns>
        public static DateTime StrToDataTime(string str, DateTime def)
        {
            DateTime dt;
            return DateTime.TryParse(str, out dt) ? dt : def;
        }

        /// <summary>
        /// string型转换为short型,转换失败返回缺省值
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <param name="def">缺省值</param>
        /// <returns>转换后的short类型结果</returns>
        public static short StrToShort(string str, short def)
        {
            return IsInt(str) ? short.Parse(str) : def;
        }

        /// <summary>
        /// string型转换为short型,转换失败返回0
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <returns>转换后的short类型结果</returns>
        public static short StrToShort(string str)
        {
            return IsInt(str) ? short.Parse(str) : (short)0;
        }

        /// <summary>
        /// 返回URL中结尾的文件名
        /// </summary>		
        public static string GetFileName(string url)
        {
            if (string.IsNullOrEmpty(url))
                return string.Empty;
            //是否有参数
            if (url.IndexOf("?", StringComparison.Ordinal) != -1)
            {
                //去掉参数
                string noquery = url.Substring(0, url.IndexOf("?", StringComparison.Ordinal));

                //根据/分组
                string[] filenames = noquery.Split(new[] { '/' });

                //文件名
                string filename = filenames[filenames.Length - 1];

                return filename;
            }
            return Path.GetFileName(url);
        }

        /// <summary>
        /// 返回字符串真实长度, 1个汉字长度为2
        /// </summary>
        /// <returns></returns>
        public static int GetLength(string str)
        {
            return string.IsNullOrEmpty(str) ? 0 : Encoding.Default.GetBytes(str).Length;
        }

        /// <summary>
        /// 将DateTime时间换成中文
        /// </summary>
        /// <example>
        /// 2012-12-21 12:12:21.012 → 1月前
        /// 2011-12-21 12:12:21.012 → 1年前
        /// </example>
        /// <param name="datetime">时间</param>
        /// <returns></returns>
        public static string DateTimeToChsStr(DateTime datetime)
        {
            var ts = DateTime.Now - datetime;
            if ((int)ts.TotalDays >= 365)
                return (int)ts.TotalDays / 365 + "年前";
            if ((int)ts.TotalDays >= 30 && ts.TotalDays <= 365)
                return (int)ts.TotalDays / 30 + "月前";
            if ((int)ts.TotalDays == 1)
                return "昨天";
            if ((int)ts.TotalDays == 2)
                return "前天";
            if ((int)ts.TotalDays >= 3 && ts.TotalDays <= 30)
                return (int)ts.TotalDays + "天前";
            if ((int)ts.TotalDays == 0)
            {
                if ((int)ts.TotalHours != 0)
                    return (int)ts.TotalHours + "小时前";
                if ((int)ts.TotalMinutes == 0)
                    return "刚刚";
                return (int)ts.TotalMinutes + "分钟前";
            }
            return datetime.ToString("yyyy年MM月dd日");
        }

        /// <summary>
        /// 将普通字符串转换为Slug
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>Slug</returns>
        public static string StrToSlug(string str)
        {
            return Regex.Replace(str.ToLower(), @"\s+", "-");
        }

        /// <summary>
        /// 从字符串的指定位置截取指定长度的子字符串(过时)
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <param name="startIndex">子字符串的起始位置</param>
        /// <param name="length">子字符串的长度</param>
        /// <returns>子字符串</returns>
        public static string CutString(string str, int startIndex, int length)
        {
            return CutString(str, startIndex, length, string.Empty);
        }

        /// <summary>
        /// 从字符串的指定位置开始截取到字符串结尾的了符串
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <param name="length">截取长度</param>
        /// <returns>子字符串</returns>
        public static string CutString(string str, int length)
        {
            return CutString(str, 0, length, string.Empty);
        }

        /// <summary>
        /// 截取字符
        /// </summary>
        /// <param name="str">原字符串</param>
        /// <param name="length">截取长度</param>
        /// <param name="def"></param>
        /// <returns></returns>
        public static string CutString(string str, int length, string def)
        {
            return CutString(str, 0, length, def);
        }

        /// <summary>
        /// 截取字符串
        /// </summary>
        /// <param name="str"></param>
        /// <param name="startIndex"></param>
        /// <param name="length"></param>
        /// <param name="def"></param>
        /// <returns></returns>
        public static string CutString(string str, int startIndex, int length, string def)
        {
            if (startIndex >= 0)
            {
                if (length < 0)
                {
                    length = length * -1;
                    if (startIndex - length < 0)
                    {
                        length = startIndex;
                        startIndex = 0;
                    }
                    else
                        startIndex = startIndex - length;
                }
                if (startIndex > str.Length)
                    return string.Empty;
            }
            else
            {
                if (length < 0)
                    return string.Empty;
                if (length + startIndex > 0)
                {
                    length = length + startIndex;
                    startIndex = 0;
                }
                else
                    return string.Empty;
            }
            if (str.Length - startIndex <= length)
            {
                length = str.Length - startIndex;
                def = string.Empty;
            }
            try
            {
                return str.Substring(startIndex, length) + def;
            }
            catch
            {
                return str + def;
            }
        }


        #endregion

        #region 字符串校验

        /// <summary>
        /// 检测指定字符串是否有SQL危险字符
        /// 没有返回true
        /// </summary>
        /// <param name="str">指定字符串</param>
        /// <returns>真或假</returns>
        public static bool IsSafeSqlString(string str)
        {
            return !Regex.IsMatch(str, @"[-|;|,|\/|\(|\)|\[|\]|\}|\{|%|@|\*|!|\']");
        }

        /// <summary>
        /// 判断指定字符串是否为合法IP地址
        /// </summary>
        /// <param name="str">指定字符串</param>
        /// <returns>真或假</returns>
        public static bool IsIP(string str)
        {
            return Regex.IsMatch(str, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
        }

        /// <summary>
        ///  判断指定字符串是否合法的日期格式
        /// </summary>
        /// <param name="str">指定字符串</param>
        /// <returns>真或假</returns>
        public static bool IsDataTime(string str)
        {
            DateTime dt;
            return DateTime.TryParse(str, out dt);
        }

        /// <summary>
        /// 判断指定的字符串是否为数字
        /// </summary>
        /// <param name="str">要确认的字符串</param>
        /// <returns>真或假</returns>
        public static bool IsInt(string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            return Regex.IsMatch(str, "^-?\\d+$");
        }

        /// <summary>
        /// 判断指定的字符串是否为Url地址
        /// </summary>
        /// <param name="str">要确认的字符串</param>
        /// <returns>真或假</returns>
        public static bool IsUrl(string str)
        {
            return Regex.IsMatch(str, "(http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?");
        }

        /// <summary>
        /// 判断指定的字符串是否为合法Email
        /// </summary>
        /// <param name="str">指定的字符串</param>
        /// <returns>真或假</returns>
        public static bool IsEmail(string str)
        {
            return Regex.IsMatch(str, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
        }

        #endregion

        #region 加密方法
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="str">要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string Encrypt(string str)
        {
            var key = string.Empty;
            var md5 = MD5.Create();
            var bytes = md5.ComputeHash(Encoding.Default.GetBytes(key));
            var eKey = new StringBuilder();
            foreach (var item in bytes)
            {
                eKey.Append(item.ToString("x"));
            }
            bytes = md5.ComputeHash(Encoding.Default.GetBytes(str + eKey));
            var pwd = new StringBuilder();
            foreach (var item in bytes)
            {
                pwd.Append(item.ToString("x"));
            }
            return pwd.ToString();
        }

        /// <summary>
        /// 将指定字符串以指定格式加密, 返回一个加密过后的字符串
        /// 不推荐使用!!
        /// </summary>
        /// <param name="str">指定字符串</param>
        /// <param name="format">指定格式("SHA1"|"MD5")</param>
        /// <returns></returns>
        public static string Encrypt(string str, string format)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(str, format);
        }

        /// <summary>
        /// 获取文件的MD5值
        /// </summary>
        /// <param name="stream">文件流</param>
        /// <returns>该文件的MD5值</returns>
        public static String GetStreamMD5(Stream stream)
        {
            string strResult = string.Empty;
            string strHashData = string.Empty;
            var oMD5Hasher = new MD5CryptoServiceProvider();
            byte[] arrbytHashValue = oMD5Hasher.ComputeHash(stream);
            //由以连字符分隔的十六进制对构成的String，其中每一对表示value 中对应的元素；例如“F-2C-4A”
            strHashData = BitConverter.ToString(arrbytHashValue);
            //替换-
            strHashData = strHashData.Replace("-", "");
            strResult = strHashData;
            return strResult;
        }

        /// <summary>
        /// 加密一个Cookie值
        /// </summary>
        /// <param name="strCookie">要加密的Cookie值</param>
        /// <returns>加密后的Cookie值</returns>
        public static string EncryptCookie(string strCookie)
        {
            var ticket = new FormsAuthenticationTicket(strCookie, true, 2);
            return FormsAuthentication.Encrypt(ticket);
        }

        /// <summary>
        /// 解密一个Cookie值
        /// </summary>
        /// <param name="strCookie">要解密的Cookie值</param>
        /// <returns>解密后的Cookie值</returns>
        public static string DecryptCookie(string strCookie)
        {
            var ticket = FormsAuthentication.Decrypt(strCookie);
            return ticket != null ? ticket.Name : string.Empty;
        }

        #endregion

        #region 常用操作

        /// <summary>
        /// 取得Gravatar用的MD5
        /// </summary>
        /// <param name="email">邮件地址</param>
        /// <returns>返回Gravatar用MD5值</returns>
        public static string GravatarMD5(string email)
        {
            string result = string.Empty;
            if (!string.IsNullOrEmpty(email))
            {
                string file = FormsAuthentication.HashPasswordForStoringInConfigFile(email, "MD5");
                if (file != null)
                    result = file.ToLower();
            }
            return result;
        }
        #endregion

        static readonly Random Random = new Random(DateTime.Now.Millisecond);
        /// <summary>
        /// 获取随机数
        /// </summary>
        public static int GetRandom(int minNum, int maxNum)
        {
            return Random.Next(minNum, maxNum);
        }
    }
    /// <summary>
    /// 拓展方法
    /// </summary>
    public static class StringExt
    {
        /// <summary>
        /// 将指定普通文本转换成HTML文本, 返回转换后HTML文本
        /// </summary>
        /// <param name="s">要转换的普通文本</param>
        /// <returns>HTML文本</returns>
        public static string ToHtml(this string s)
        {
            var sb = new StringBuilder(s);
            sb.Replace("&", "&amp;");
            sb.Replace("<", "&lt;");
            sb.Replace(">", "&gt;");
            sb.Replace("\"", "&quot;");
            sb.Replace(" ", "&nbsp;");
            sb.Replace("\t", "&nbsp;&nbsp;");
            sb.Replace("\r", "");
            sb.Replace("\n", "<br />");
            return sb.ToString();
        }
        /// <summary>
        /// 对字符串进行 HTML 编码并返回已编码的字符串
        /// </summary>
        /// <param name="s">要编码的文本字符串</param>
        /// <returns>HTML 已编码的文本</returns>
        public static string HtmlEncode(this string s)
        {
            return HttpContext.Current.Server.HtmlEncode(s);
        }
        /// <summary>
        ///  对 HTML 编码的字符串进行解码，并返回已解码的字符串
        /// </summary>
        /// <param name="s">要解码的文本字符串</param>
        /// <returns>已解码的字符串</returns>
        public static string HtmlDecode(this string s)
        {
            return HttpContext.Current.Server.HtmlDecode(s);
        }
        /// <summary>
        /// 对 URL 字符串进行编码, 返回 URL 字符串的编码结果
        /// </summary>
        /// <param name="s">要编码的文本</param>
        /// <returns>一个已编码的字符串</returns>
        public static string UrlEncode(this string s)
        {
            return HttpUtility.UrlEncode(s);
        }
        /// <summary>
        /// 对 URL 字符串进行解码, 返回 URL 字符串的解码结果
        /// </summary>
        /// <param name="s">要解码的文本</param>
        /// <returns>解码结果</returns>
        public static string UrlDecode(this string s)
        {
            return HttpUtility.UrlDecode(s);
        }
        /// <summary>
        /// 移除Html标记
        /// </summary>
        /// <param name="s">包括HTML的源码</param>   
        ///<returns>已经去除后的文字</returns>   
        public static string TrimHtml(this string s)
        {
            return StringHelper.RemoveHtml(s);
        }
        /// <summary>
        /// 编码成 sql 文本可以接受的格式
        /// </summary>
        public static string SqlEncode(this string s)
        {
            if (string.IsNullOrEmpty(s))
            {
                return string.Empty;
            }
            return s.Trim().Replace("'", "''");
        }
        /// <summary>
        /// string型转换为int型,转换失败返回缺省值
        /// </summary>
        /// <param name="s">要转换的字符串</param>
        /// <param name="def">缺省值</param>
        /// <returns>转换后的int类型结果</returns>
        public static int ToInt(this string s, int def)
        {
            return StringHelper.IsInt(s) ? int.Parse(s) : def;
        }
        /// <summary>
        /// string型转换为int型,转换失败返回0
        /// </summary>
        /// <param name="s">要转换的字符串</param>
        /// <returns>转换后的int类型结果</returns>
        public static int ToInt(this string s)
        {
            return StringHelper.IsInt(s) ? int.Parse(s) : 0;
        }
        /// <summary>
        /// string型转换为bool型,转换失败返回缺省值
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <param name="def">缺省值</param>
        /// <returns>转换后的bool类型结果</returns>
        public static bool ToBoolean(this string str, bool def)
        {
            bool b;
            return bool.TryParse(str, out b) ? b : def;
        }
        /// <summary>
        /// string型转换为bool型,转换失败返回false
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <returns>转换后的bool类型结果</returns>
        public static bool ToBoolean(this string str)
        {
            bool b;
            return bool.TryParse(str, out b) ? b : false;
        }
        /// <summary>
        /// string型转换为DateTime型,转换失败返回最小时间
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <returns>转换后的DateTime类型结果</returns>
        public static DateTime ToDataTime(this string str)
        {
            DateTime dt;
            return DateTime.TryParse(str, out dt) ? dt : DateTime.MinValue;
        }
        /// <summary>
        /// string型转换为DateTime型,转换失败返回缺省值
        /// </summary>
        /// <param name="str">要转换的字符串</param>
        /// <param name="def">缺省值</param>
        /// <returns>转换后的DateTime类型结果</returns>
        public static DateTime ToDataTime(this string str, DateTime def)
        {
            DateTime dt;
            return DateTime.TryParse(str, out dt) ? dt : def;
        }
        /// <summary>
        /// 将普通字符串转换为Slug
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>Slug</returns>
        public static string ToSlug(this string str)
        {
            return Regex.Replace(str.ToLower(), @"\s+", "-");
        }
        /// <summary>
        /// string型转换为short型,转换失败返回缺省值
        /// </summary>
        /// <param name="s">要转换的字符串</param>
        /// <param name="def">缺省值</param>
        /// <returns>转换后的short类型结果</returns>
        public static short ToShort(this string s, short def)
        {
            return StringHelper.IsInt(s) ? short.Parse(s) : def;
        }
        /// <summary>
        /// string型转换为short型,转换失败返回0
        /// </summary>
        /// <param name="s">要转换的字符串</param>
        /// <returns>转换后的short类型结果</returns>
        public static short ToShort(this string s)
        {
            return StringHelper.IsInt(s) ? short.Parse(s) : (short)0;
        }
        /// <summary>
        /// 返回字符串真实长度, 1个汉字长度为2
        /// </summary>
        /// <returns></returns>
        public static int RealLength(this string s)
        {
            return string.IsNullOrEmpty(s) ? 0 : Encoding.Default.GetBytes(s).Length;
        }
        /// <summary>
        /// 将DateTime时间换成中文
        /// </summary>
        /// <example>
        /// 2012-12-21 12:12:21.012 → 1月前
        /// 2011-12-21 12:12:21.012 → 1年前
        /// </example>
        /// <param name="datetime">时间</param>
        /// <returns></returns>
        public static string ToChsStr(this DateTime datetime)
        {
            var ts = DateTime.Today - datetime;
            if ((int)ts.TotalDays >= 365)
                return (int)ts.TotalDays / 365 + "年前";
            if ((int)ts.TotalDays >= 30 && ts.TotalDays <= 365)
                return (int)ts.TotalDays / 30 + "月前";
            if ((int)ts.TotalDays == 1)
                return "昨天";
            if ((int)ts.TotalDays == 2)
                return "前天";
            if ((int)ts.TotalDays >= 3 && ts.TotalDays <= 30)
                return (int)ts.TotalDays + "天前";
            if ((int)ts.TotalDays == 0)
            {
                if ((int)ts.TotalHours != 0)
                    return (int)ts.TotalHours + "小时前";
                if ((int)ts.TotalMinutes == 0)
                    return "刚刚";
                return (int)ts.TotalMinutes + "分钟前";
            }
            return datetime.ToString("yyyy年MM月dd日");
        }
        /// <summary>
        /// 检测指定字符串是否有SQL危险字符
        /// 没有返回true
        /// </summary>
        /// <param name="sql">指定字符串</param>
        /// <returns>真或假</returns>
        public static bool IsSafeSqlString(this string sql)
        {
            return !Regex.IsMatch(sql, @"[-|;|,|\/|\(|\)|\[|\]|\}|\{|%|@|\*|!|\']");
        }
        /// <summary>
        /// 判断指定字符串是否为合法IP地址
        /// </summary>
        /// <param name="s">指定字符串</param>
        /// <returns>真或假</returns>
        public static bool IsIP(this string s)
        {
            return Regex.IsMatch(s, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
        }
        /// <summary>
        ///  判断指定字符串是否合法的日期格式
        /// </summary>
        /// <param name="s">指定字符串</param>
        /// <returns>真或假</returns>
        public static bool IsDateTime(this string s)
        {
            DateTime dt;
            return DateTime.TryParse(s, out dt);
        }
        /// <summary>
        /// 判断指定的字符串是否为数字
        /// </summary>
        /// <param name="s">要确认的字符串</param>
        /// <returns>真或假</returns>
        public static bool IsInt(this string s)
        {
            if (string.IsNullOrEmpty(s))
                return false;
            return Regex.IsMatch(s, "^-?\\d+$");
        }
        /// <summary>
        /// 判断指定的字符串是否为Url地址
        /// </summary>
        /// <param name="s">要确认的字符串</param>
        /// <returns>真或假</returns>
        public static bool IsUrl(this string s)
        {
            return Regex.IsMatch(s, "(http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?");
        }
        /// <summary>
        /// 判断指定的字符串是否为合法Email
        /// </summary>
        /// <param name="s">指定的字符串</param>
        /// <returns>真或假</returns>
        public static bool IsEmail(this string s)
        {
            return Regex.IsMatch(s, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
        }
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="s">要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string Encrypt(this string s)
        {
            var key = string.Empty;
            var md5 = MD5.Create();
            var bytes = md5.ComputeHash(Encoding.Default.GetBytes(key));
            var eKey = new StringBuilder();
            foreach (var item in bytes)
            {
                eKey.Append(item.ToString("x"));
            }
            bytes = md5.ComputeHash(Encoding.Default.GetBytes(s + eKey));
            var pwd = new StringBuilder();
            foreach (var item in bytes)
            {
                pwd.Append(item.ToString("x"));
            }
            return pwd.ToString();
        }
        /// <summary>
        /// 将指定字符串以指定格式加密, 返回一个加密过后的字符串
        /// 不推荐使用!!
        /// </summary>
        /// <param name="s">指定字符串</param>
        /// <param name="format">指定格式("SHA1"|"MD5")</param>
        /// <returns></returns>
        public static string Encrypt(this string s, string format)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(s, format);
        }
        /// <summary>
        /// 获取文件的MD5值
        /// </summary>
        /// <param name="stream">文件流</param>
        /// <returns>该文件的MD5值</returns>
        public static String StreamMD5(this Stream stream)
        {
            string strResult = string.Empty;
            string strHashData = string.Empty;
            var oMD5Hasher = new MD5CryptoServiceProvider();
            byte[] arrbytHashValue = oMD5Hasher.ComputeHash(stream);
            //由以连字符分隔的十六进制对构成的String，其中每一对表示value 中对应的元素；例如“F-2C-4A”
            strHashData = BitConverter.ToString(arrbytHashValue);
            //替换-
            strHashData = strHashData.Replace("-", "");
            strResult = strHashData;
            return strResult;
        }
        /// <summary>
        /// 加密一个Cookie值
        /// </summary>
        /// <param name="strCookie">要加密的Cookie值</param>
        /// <returns>加密后的Cookie值</returns>
        public static string EncryptCookie(this string strCookie)
        {
            var ticket = new FormsAuthenticationTicket(strCookie, true, 2);
            return FormsAuthentication.Encrypt(ticket);
        }
        /// <summary>
        /// 解密一个Cookie值
        /// </summary>
        /// <param name="strCookie">要解密的Cookie值</param>
        /// <returns>解密后的Cookie值</returns>
        public static string DecryptCookie(this string strCookie)
        {
            var ticket = FormsAuthentication.Decrypt(strCookie);
            return ticket != null ? ticket.Name : string.Empty;
        }
        /// <summary>
        /// 取得Gravatar用的MD5
        /// </summary>
        /// <param name="email">邮件地址</param>
        /// <returns>返回Gravatar用MD5值</returns>
        public static string GravatarMD5(this string email)
        {
            string result = string.Empty;
            if (!string.IsNullOrEmpty(email))
            {
                string file = FormsAuthentication.HashPasswordForStoringInConfigFile(email, "MD5");
                if (file != null)
                    result = file.ToLower();
            }
            return result;
        }
    }
}
